package com.xd.core.company.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xd.common.base.CustomRowHeightColWidthHandler;
import com.xd.common.base.RowHeightColWidthModel;
import com.xd.common.constant.SysConstant;
import com.xd.common.exception.XkdException;
import com.xd.common.properties.PassWordKeyProperties;
import com.xd.common.util.RSAUtils;
import com.xd.common.util.SecurityUtil;
import com.xd.common.util.XkdUtil;
import com.xd.core.business.entity.IncomingInfo;
import com.xd.core.business.entity.InsuranceCompanyInfo;
import com.xd.core.business.entity.OutInfo;
import com.xd.core.business.entity.ProductCompanyTiered;
import com.xd.core.business.mapper.IncomingInfoMapper;
import com.xd.core.business.mapper.InsuranceCompanyInfoMapper;
import com.xd.core.business.mapper.OutInfoMapper;
import com.xd.core.business.mapper.ProductCompanyTieredMapper;
import com.xd.core.business.vo.IncomingInfoPageVo;
import com.xd.core.company.dto.*;
import com.xd.core.company.entity.*;
import com.xd.core.company.mapper.*;
import com.xd.core.company.service.ICompanyService;
import com.xd.core.company.vo.*;
import com.xd.core.debt.entity.Debt;
import com.xd.core.debt.mapper.DebtMapper;
import com.xd.core.finance.entity.ConsumeDetail;
import com.xd.core.finance.mapper.ConsumeDetailMapper;
import com.xd.core.mission.entity.MissionCenterInfo;
import com.xd.core.mission.mapper.MissionCenterInfoMapper;
import com.xd.core.product.entity.Product;
import com.xd.core.product.entity.ProductCompany;
import com.xd.core.product.mapper.ProductCompanyMapper;
import com.xd.core.product.mapper.ProductMapper;
import com.xd.core.system.entity.GroupInfo;
import com.xd.core.system.entity.SysUser;
import com.xd.core.system.entity.SysUserRole;
import com.xd.core.system.entity.UserGroup;
import com.xd.core.system.mapper.GroupInfoMapper;
import com.xd.core.system.mapper.SysUserMapper;
import com.xd.core.system.mapper.SysUserRoleMapper;
import com.xd.core.system.mapper.UserGroupMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 企业信息 服务实现类
 * </p>
 *
 * @author ZX
 * @since 2025-02-23
 */
@Slf4j
@Service
public class CompanyServiceImpl extends ServiceImpl<CompanyMapper, Company> implements ICompanyService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private GroupInfoMapper groupInfoMapper;
    @Autowired
    private CompanyAccountMapper companyAccountMapper;
    @Autowired
    private UserGroupMapper userGroupMapper;
    @Autowired
    private CapitalAgencyMapper capitalAgencyMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private AgencyCompanyCheckMapper agencyCompanyCheckMapper;
    @Autowired
    private ProductCompanyMapper productCompanyMapper;
    @Autowired
    private PassWordKeyProperties passWordKeyProperties;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private OutInfoMapper outInfoMapper;
    @Autowired
    private IncomingInfoMapper incomingInfoMapper;
    @Autowired
    private ConsumeDetailMapper consumeDetailMapper;
    @Autowired
    private DebtMapper debtMapper;
    @Autowired
    private CapitalBlocMapper capitalBlocMapper;
    @Autowired
    private CompanyContractMapper companyContractMapper;
    @Autowired
    private MissionCenterInfoMapper missionCenterInfoMapper;
    @Autowired
    private ProductCompanyTieredMapper productCompanyTieredMapper;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private InsuranceCompanyInfoMapper insuranceCompanyInfoMapper;
    @Value("${spring.profiles.active}")
    private String active;


    @Value("${image.localPathDir}")
    private String localPathDir;
    @Value("${image.exportFile}")
    private String exportFile;
    private static final BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
    private static final String redisLogin = "login:";
    private static final String redisToken = "token:";
    @Autowired
    private ProductMapper productMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addCapitalUser(AddCapitalUserDto addCapitalUserDto) throws Exception {
        if (!checkPhoneRepetition(addCapitalUserDto.getPhone()))
            throw new XkdException("用户手机号已注册");
        if (!checkUnifiedSocialCreditCode(addCapitalUserDto.getUnifiedSocialCreditCode()))
            throw new XkdException("统一社会信用代码已注册");
        /*
         * 插入公司
         * */
        Company company = new Company();
        BeanUtil.copyProperties(addCapitalUserDto, company);
        company.setCompanyType(SysConstant.COMPANY_TYPE_ONE);
        company.setCapitalId(addCapitalUserDto.getId());
        companyMapper.insert(company);
        /*
         * 是否绑定集团
         * */
        if (addCapitalUserDto.getBlocId() != null) {//绑集团
            CapitalBloc capitalBloc = new CapitalBloc();
            capitalBloc.setCapitalId(company.getId());
            capitalBloc.setBlocId(addCapitalUserDto.getBlocId());
            capitalBlocMapper.insert(capitalBloc);
        }
        /*
         * 插入用户
         * */
        SysUser sysUser = new SysUser();
        sysUser.setPhone(addCapitalUserDto.getPhone());
        sysUser.setUserName(addCapitalUserDto.getCompanyName());
        //校验密码正则规则
        String decrypt = RSAUtils.privateDecrypt(addCapitalUserDto.getPassword(), passWordKeyProperties.getPrivateKey());
        String rex = "^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{8,16}$";
        if (!Pattern.matches(rex, decrypt)) {
            throw new XkdException("密码不符合规则");
        }
        sysUser.setPassword(bCryptPasswordEncoder.encode(decrypt));
        sysUser.setCompanyId(company.getId());
        sysUser.setCompanyType(SysConstant.USER_COMPANY_TYPE_TOW);
        sysUser.setUserType(SysConstant.USER_TYPE_P);
        sysUser.setCreateBy(SecurityUtil.getLoginUserId());
        sysUser.setDataPertType(SysConstant.DATA_PERT_TYPE_FOUR);
        sysUserMapper.insert(sysUser);
        /*
         * 绑定资方角色
         * */
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setCompanyId(company.getId())
                .setUserId(sysUser.getId())
                .setRoleId(SysConstant.SYS_ROLE_CAPITAL_SUPER);
        sysUserRoleMapper.insert(sysUserRole);
        /*
         * 新建公司部门
         * */
        GroupInfo groupInfo = new GroupInfo();
        groupInfo.setCompanyId(company.getId())
                .setPid(SysConstant.PID_PARENT)
                .setGroupName(company.getCompanyName() + "总部");
        groupInfoMapper.insert(groupInfo);

        UserGroup userGroup = new UserGroup();
        userGroup.setCompanyId(company.getId())
                .setUserId(sysUser.getId())
                .setGroupId(groupInfo.getId());
        userGroupMapper.insert(userGroup);
        /*
         * 产品服务费率配置
         * */
        List<ProductCompany> productCompanies = addCapitalUserDto.getProductCompanies();
        productCompanies.forEach(p -> {
            p.setCompanyId(company.getId());
        });
        if (CollectionUtil.isNotEmpty(productCompanies)) {
            productCompanyMapper.insertBatch(productCompanies);
        }
        List<ProductCompanyTiered> productCompanyTiereds = addCapitalUserDto.getProductCompanyTiereds();
        if (CollectionUtil.isNotEmpty(productCompanyTiereds)) {
            // 提取产品ID列表并查询产品信息
            List<Integer> productIds = productCompanyTiereds.stream()
                    .map(ProductCompanyTiered::getProductId)
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(productIds)) {
                Map<Integer, Product> productMap = productMapper.selectList(
                                new LambdaQueryWrapper<Product>().in(Product::getProductId, productIds)
                        ).stream()
                        .collect(Collectors.toMap(Product::getProductId, Function.identity()));

                // 验证每个阶梯收费设置
                for (ProductCompanyTiered tiered : productCompanyTiereds) {
                    Product product = productMap.get(tiered.getProductId());
                    if (product == null) {
                        throw new XkdException("关联的产品不存在: " + tiered.getProductId());
                    }

                    // 验证阶梯金额是否在产品允许范围内
                    if (tiered.getChargeAmountMin().compareTo(product.getMinAmount()) < 0 ||
                            tiered.getChargeAmountMax().compareTo(product.getMaxAmount()) > 0) {
                        throw new XkdException("阶梯收费金额超出产品金额限制");
                    }

                    tiered.setCompanyId(company.getId());
                }

                // 批量插入阶梯收费设置
                productCompanyTieredMapper.insertBatch(productCompanyTiereds);

            }
            // 按产品分组并验证阶梯连续性
            Map<Integer, List<ProductCompanyTiered>> productTierMap = productCompanyTiereds.stream()
                    .collect(Collectors.groupingBy(ProductCompanyTiered::getProductId));

            for (List<ProductCompanyTiered> tierList : productTierMap.values()) {
                // 按ID排序确保顺序
                tierList.sort(Comparator.comparingInt(ProductCompanyTiered::getId));

                // 验证阶梯连续性
                for (int i = 1; i < tierList.size(); i++) {
                    if (tierList.get(i).getChargeAmountMin().compareTo(tierList.get(i - 1).getChargeAmountMax()) != 0) {
                        throw new XkdException("阶梯收费设置不连续，最小值必须等于上一级最大值");
                    }
                }
            }
        }

        /*
         * 插入电子账号
         * */
        CompanyAccount companyAccount = new CompanyAccount();
        companyAccount.setCompanyId(company.getId());
        companyAccountMapper.insert(companyAccount);
        //新增资方作为投保公司
        InsuranceCompanyInfo insuranceCompanyInfo = BeanUtil.copyProperties(company, InsuranceCompanyInfo.class);
        insuranceCompanyInfo.setInsuranceCompanyName(addCapitalUserDto.getCompanyName());
        insuranceCompanyInfo.setCompanyId(company.getId());
        insuranceCompanyInfo.setOpeningBankName(company.getOpeningBank());
        insuranceCompanyInfo.setOpeningBankAccount(company.getBankAccount());
    }

    @Override
    public void addAgencyUser(AddAgencyUserDto addAgencyUserDto) {
        if (!checkPhoneRepetition(addAgencyUserDto.getPhone()))
            throw new XkdException("用户手机号已注册");
        if (!checkUnifiedSocialCreditCode(addAgencyUserDto.getUnifiedSocialCreditCode()))
            throw new XkdException("统一社会信用代码已注册");
        /*
         * 插入审核信息
         * */
        AgencyCompanyCheck agencyCompanyCheck = new AgencyCompanyCheck();
        BeanUtil.copyProperties(addAgencyUserDto, agencyCompanyCheck);
        //校验密码正则规则
        String decrypt = RSAUtils.privateDecrypt(agencyCompanyCheck.getPassword(), passWordKeyProperties.getPrivateKey());
        String rex = "^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{8,16}$";
        if (!Pattern.matches(rex, decrypt)) {
            throw new XkdException("密码不符合规则");
        }

        agencyCompanyCheck.setPassword(bCryptPasswordEncoder.encode(decrypt));
        agencyCompanyCheck.setCreateBy(SecurityUtil.getLoginUserId());

        agencyCompanyCheckMapper.insert(agencyCompanyCheck);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void checkAgencyUser(CheckAgencyUserDto checkAgencyUserDto) {
        Integer id = checkAgencyUserDto.getId();
        AgencyCompanyCheck agencyCompanyCheck = agencyCompanyCheckMapper.selectById(id);
        if (agencyCompanyCheck.getCheckStatus().equals(SysConstant.AGENCY_CHECK_STATUS_TOW))
            throw new XkdException("审核状态非待审状态");
        //审核通过
        if (checkAgencyUserDto.getCheckStatus().equals(SysConstant.AGENCY_CHECK_STATUS_TOW)) {
            //查询电话是否已注册
            if (!checkPhoneRepetition(agencyCompanyCheck.getPhone()))
                throw new XkdException("用户手机号已注册");
            if (!checkUnifiedSocialCreditCode(agencyCompanyCheck.getUnifiedSocialCreditCode()))
                throw new XkdException("统一社会信用代码已注册");
            /*
             * 插入公司
             * */
            Company company = new Company();
            BeanUtil.copyProperties(agencyCompanyCheck, company);
            company.setCompanyType(SysConstant.COMPANY_TYPE_TOW);
            company.setCapitalId(agencyCompanyCheck.getCapitalId());
            companyMapper.insert(company);
            /*
             * 绑定资方企业
             * */
            CapitalAgency capitalAgency = new CapitalAgency();
            capitalAgency.setAgencyId(company.getId());
            capitalAgency.setCapitalId(agencyCompanyCheck.getCapitalId());
            capitalAgencyMapper.insert(capitalAgency);
            /*
             * 插入用户表
             * */
            SysUser sysUser = new SysUser();

            sysUser.setPhone(agencyCompanyCheck.getPhone());
            sysUser.setUserName(agencyCompanyCheck.getCompanyName());
            sysUser.setPassword(agencyCompanyCheck.getPassword());
            sysUser.setCompanyId(company.getId());
            sysUser.setCompanyType(SysConstant.USER_COMPANY_TYPE_THREE);
            sysUser.setUserType(SysConstant.USER_TYPE_P);
            sysUser.setCreateBy(agencyCompanyCheck.getCreateBy());
            sysUser.setDataPertType(SysConstant.DATA_PERT_TYPE_FOUR);
            sysUserMapper.insert(sysUser);
            /*
             * 绑定代理角色
             * */
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setCompanyId(company.getId())
                    .setUserId(sysUser.getId())
                    .setRoleId(SysConstant.SYS_ROLE_AGENCY_SUPER);
            sysUserRoleMapper.insert(sysUserRole);
            /*
             * 新建公司部门
             * */
            GroupInfo groupInfo = new GroupInfo();
            groupInfo.setCompanyId(company.getId())
                    .setPid(SysConstant.PID_PARENT)
                    .setGroupName(company.getCompanyName() + "总部");
            groupInfoMapper.insert(groupInfo);

            UserGroup userGroup = new UserGroup();
            userGroup.setCompanyId(company.getId())
                    .setUserId(sysUser.getId())
                    .setGroupId(groupInfo.getId());
            userGroupMapper.insert(userGroup);
            /*
             * 更新审核状态
             * */
            agencyCompanyCheckMapper.updateCheckStatus(checkAgencyUserDto.getId(), SysConstant.AGENCY_CHECK_STATUS_TOW);
        } else {
            agencyCompanyCheckMapper.updateCheckStatusFail(checkAgencyUserDto.getId(), SysConstant.AGENCY_CHECK_STATUS_THREE, checkAgencyUserDto.getCheckOpinion());
        }
    }

    @Override
    public GetCheckDetail getCheckDetail(Integer id) {
        return agencyCompanyCheckMapper.getCheckDetail(id);
    }

    @Override
    public void againAddAgencyUser(AddAgencyUserDto addAgencyUserDto) {
        String rex = "^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{8,16}$";
        Integer id = addAgencyUserDto.getId();
        AgencyCompanyCheck companyCheck = agencyCompanyCheckMapper.selectById(id);
        if (!SysConstant.AGENCY_CHECK_STATUS_TOW.equals(companyCheck.getCheckStatus())) {
            if (!checkPhoneRepetition(addAgencyUserDto.getPhone()))
                throw new XkdException("用户手机号已注册");
            if (!checkUnifiedSocialCreditCode(addAgencyUserDto.getUnifiedSocialCreditCode()))
                throw new XkdException("统一社会信用代码已注册");
            /*
             * 插入审核信息
             * */
            AgencyCompanyCheck agencyCompanyCheck = new AgencyCompanyCheck();
            BeanUtil.copyProperties(addAgencyUserDto, agencyCompanyCheck);
            if (!StringUtils.isEmpty(addAgencyUserDto.getPassword())) {
                //校验密码正则规则
                String decrypt = RSAUtils.privateDecrypt(agencyCompanyCheck.getPassword(), passWordKeyProperties.getPrivateKey());
                if (!Pattern.matches(rex, decrypt)) {
                    throw new XkdException("密码不符合规则");
                }
                agencyCompanyCheck.setPassword(bCryptPasswordEncoder.encode(decrypt));
            }
            agencyCompanyCheck.setCheckStatus(SysConstant.AGENCY_CHECK_STATUS_ONE);
            agencyCompanyCheck.setCheckTime(null);
            LambdaUpdateWrapper<AgencyCompanyCheck> lqw = new LambdaUpdateWrapper<>();
            lqw.eq(AgencyCompanyCheck::getId, agencyCompanyCheck.getId()).
                    set(AgencyCompanyCheck::getCheckTime, agencyCompanyCheck.getCheckTime());
            agencyCompanyCheckMapper.update(agencyCompanyCheck, lqw);
        } else {
            //校验密码正则规则
            String decrypt = RSAUtils.privateDecrypt(addAgencyUserDto.getPassword(), passWordKeyProperties.getPrivateKey());
            if (!Pattern.matches(rex, decrypt)) {
                throw new XkdException("密码不符合规则");
            }
            companyCheck.setPassword(bCryptPasswordEncoder.encode(decrypt));
            LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhone, addAgencyUserDto.getPhone());
            SysUser sysUser = sysUserMapper.selectOne(wrapper);
            agencyCompanyCheckMapper.updateById(companyCheck);
            sysUserMapper.updatePassword(addAgencyUserDto, sysUser.getId());
            redisTemplate.delete(redisLogin + sysUser.getId());
            redisTemplate.delete(redisToken + sysUser.getId());
        }
    }

    //检查手机号重复
    @Override
    public boolean checkPhoneRepetition(String phone) {
        if (StringUtils.isNotBlank(phone)) {
            LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<>();
            lqw.eq(SysUser::getPhone, phone);
            Integer integer = sysUserMapper.selectCount(lqw);
            //如果没有重复返回true
            return integer == 0;
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCapitalUser(AddCapitalUserDto addCapitalUserDto) {
        if (!checkPhoneRepetition(addCapitalUserDto.getPhone()))
            throw new XkdException("用户手机号已注册");
        if (!checkUnifiedSocialCreditCode(addCapitalUserDto.getUnifiedSocialCreditCode()))
            throw new XkdException("统一社会信用代码已注册");
        /*
         * 修改资方下代理商务经理
         */
        Integer companyId = addCapitalUserDto.getId();
        Company company1 = companyMapper.selectById(companyId);
        if (!addCapitalUserDto.getBusinessManager().equals(company1.getBusinessManager())) {
            companyMapper.updateBusinessManager(addCapitalUserDto.getBusinessManager(), companyId);
            agencyCompanyCheckMapper.updateBusinessManager(addCapitalUserDto.getBusinessManager(), companyId);
        }
        /*
         * 修改公司
         * */
        Company company = new Company();
        BeanUtil.copyProperties(addCapitalUserDto, company);
        LambdaUpdateWrapper<Company> companyLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        companyLambdaUpdateWrapper.eq(Company::getId, company.getId())
                .set(Company::getBlocId, addCapitalUserDto.getBlocId());
//                .set(Company::getContractChargeType,addCapitalUserDto.getContractChargeType())
//                .set(Company::getContractFee,addCapitalUserDto.getContractFee())
//                .set(Company::getContractFeeTotal,addCapitalUserDto.getContractFeeTotal())
//                .set(Company::getExecuteChargeType,addCapitalUserDto.getExecuteChargeType())
//                .set(Company::getExecuteChargeFloor,addCapitalUserDto.getExecuteChargeFloor())
//                .set(Company::getExecuteChargeRate,addCapitalUserDto.getExecuteChargeRate())
//                .set(Company::getNotarizationChargeType,addCapitalUserDto.getNotarizationChargeType())
//                .set(Company::getNotarizationChargeFloor,addCapitalUserDto.getNotarizationChargeFloor())
//                .set(Company::getNotarizationChargeRate,addCapitalUserDto.getNotarizationChargeRate())
//                .set(Company::getDepositAmount,addCapitalUserDto.getDepositAmount())
//                .set(Company::getDepositRate,addCapitalUserDto.getDepositRate())
//                .set(Company::getDepositType,addCapitalUserDto.getDepositType())
//                .set(Company::getOutServiceFee,addCapitalUserDto.getOutServiceFee())
//                .set(Company::getCollectionDeductionServiceFee,addCapitalUserDto.getCollectionDeductionServiceFee())
//                .set(Company::getCollectionTransfeServiceFee,addCapitalUserDto.getCollectionTransfeServiceFee())

        if (addCapitalUserDto.getBlocId() == null) {//解绑集团 默认为独立核算
            company.setAccountingType(SysConstant.ACCOUNTING_TYPE_ONE);
            capitalBlocMapper.delete(new LambdaQueryWrapper<CapitalBloc>().eq(CapitalBloc::getCapitalId, company.getId()));
        }
        companyMapper.update(company, companyLambdaUpdateWrapper);
        /*
         * 是否修改绑定集团
         * */
        if (addCapitalUserDto.getBlocId() != null) {//绑集团
            CapitalBloc old = capitalBlocMapper.selectOne(new LambdaQueryWrapper<CapitalBloc>().eq(CapitalBloc::getCapitalId, company.getId()));
            if (old == null) {
                CapitalBloc capitalBloc = new CapitalBloc();
                capitalBloc.setCapitalId(company.getId());
                capitalBloc.setBlocId(addCapitalUserDto.getBlocId());
                capitalBlocMapper.insert(capitalBloc);
            } else {
                LambdaQueryWrapper<CapitalBloc> capitalBlocLambdaQueryWrapper = new LambdaQueryWrapper<>();
                capitalBlocLambdaQueryWrapper.eq(CapitalBloc::getCapitalId, addCapitalUserDto.getId());
                CapitalBloc capitalBloc = new CapitalBloc();
                capitalBloc.setBlocId(addCapitalUserDto.getBlocId());
                capitalBlocMapper.update(capitalBloc, capitalBlocLambdaQueryWrapper);
            }

        }
        /*
         * 修改用户
         * */
        SysUser sysUser = new SysUser();
        sysUser.setPhone(addCapitalUserDto.getPhone());
        sysUser.setUserName(addCapitalUserDto.getCompanyName());
        //校验密码正则规则
        if (StringUtils.isNotEmpty(addCapitalUserDto.getPassword())) {
            String decrypt = RSAUtils.privateDecrypt(addCapitalUserDto.getPassword(), passWordKeyProperties.getPrivateKey());
            String rex = "^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{8,16}$";
            if (!Pattern.matches(rex, decrypt)) {
                throw new XkdException("密码不符合规则");
            }
            Integer id = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                    .eq(SysUser::getCompanyId, companyId)
                    .eq(SysUser::getUserType, SysConstant.USER_TYPE_P)).getId();
            redisTemplate.delete(redisLogin + id);
            redisTemplate.delete(redisToken + id);
            sysUser.setPassword(bCryptPasswordEncoder.encode(decrypt));
        }
        sysUserMapper.update(sysUser, new LambdaQueryWrapper<SysUser>().eq(SysUser::getCompanyId, company.getId()).eq(SysUser::getUserType, SysConstant.USER_TYPE_P));

        /*
         * 产品服务费率配置修改
         * */

        List<ProductCompany> productCompanies = addCapitalUserDto.getProductCompanies();
        if (CollectionUtil.isNotEmpty(productCompanies)) {
            productCompanyMapper.delete(new LambdaQueryWrapper<ProductCompany>().eq(ProductCompany::getCompanyId, companyId));
            productCompanyMapper.insertBatch(productCompanies);
        }

        List<ProductCompanyTiered> productCompanyTiereds = addCapitalUserDto.getProductCompanyTiereds();
        if (CollectionUtil.isNotEmpty(productCompanyTiereds)) {
            productCompanyTieredMapper.delete(new LambdaQueryWrapper<ProductCompanyTiered>().eq(ProductCompanyTiered::getCompanyId, companyId));
            // 提取产品ID列表并查询产品信息
            List<Integer> productIds = productCompanyTiereds.stream()
                    .map(ProductCompanyTiered::getProductId)
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(productIds)) {
                // 查询产品信息并转换为Map(产品ID -> 产品
                Map<Integer, Product> productMap = productMapper.selectList(
                                new LambdaQueryWrapper<Product>().in(Product::getProductId, productIds)
                        ).stream()
                        .collect(Collectors.toMap(Product::getProductId, Function.identity()));

                // 验证每个阶梯收费设置
                for (ProductCompanyTiered tiered : productCompanyTiereds) {
                    Product product = productMap.get(tiered.getProductId());
                    if (product == null) {
                        throw new XkdException("关联的产品不存在: " + tiered.getProductId());
                    }

                    // 验证阶梯金额是否在产品允许范围内
                    if (tiered.getChargeAmountMin().compareTo(product.getMinAmount()) < 0 ||
                            tiered.getChargeAmountMax().compareTo(product.getMaxAmount()) > 0) {
                        throw new XkdException("阶梯收费金额超出产品金额限制");
                    }

                    tiered.setCompanyId(company.getId());
                }

                // 批量插入阶梯收费设置
                productCompanyTieredMapper.insertBatch(productCompanyTiereds);
            }


            // 按产品分组并验证阶梯连续性
            Map<Integer, List<ProductCompanyTiered>> productTierMap = productCompanyTiereds.stream()
                    .collect(Collectors.groupingBy(ProductCompanyTiered::getProductId));

            for (List<ProductCompanyTiered> tierList : productTierMap.values()) {
                // 按ID排序确保顺序
                tierList.sort(Comparator.comparingInt(ProductCompanyTiered::getId));

                // 验证阶梯连续性
                for (int i = 1; i < tierList.size(); i++) {
                    if (tierList.get(i).getChargeAmountMin().compareTo(tierList.get(i - 1).getChargeAmountMax()) != 0) {
                        throw new XkdException("阶梯收费设置不连续，最小值必须等于上一级最大值");
                    }
                }
            }
        }
    }


    @Override
    public Page<CompanyPageVo> getAgencyList(CompanyQuery companyQuery) {
        Integer id = SecurityUtil.getLoginCompanyId();
        if (id == 0) {
            id = null;
        }
        PageHelper.startPage(companyQuery.getPageNum(), companyQuery.getPageSize());
        return (Page<CompanyPageVo>) companyMapper.queryList(id, companyQuery);
    }

    @Override
    public CompanyAgencyVo getAgencyDetail(Integer id) {
        return productCompanyMapper.getDetailById(id);
    }

    @Override
    public Page<CompanyPageVo> getAgencyList1(CompanyQuery companyQuery) {
        Integer id = SecurityUtil.getLoginCompanyId();
        if (id == 0) {
            id = null;
        }
        PageHelper.startPage(companyQuery.getPageNum(), companyQuery.getPageSize());
        return (Page<CompanyPageVo>) companyMapper.queryList1(id, companyQuery);
    }

    @Override
    public Page<CapitalPageVo> getCapitalList(CompanyQuery companyQuery) {
        String companyType = SecurityUtil.getLoginUser().getUser().getCompanyType();
        if (companyType.equals(SysConstant.USER_COMPANY_TYPE_ONE)) {
            PageHelper.startPage(companyQuery.getPageNum(), companyQuery.getPageSize());
            return (Page<CapitalPageVo>) companyMapper.getCapital(companyQuery);
        } else if (companyType.equals(SysConstant.USER_COMPANY_TYPE_FOUR)) {
            companyQuery.setBlocId(SecurityUtil.getLoginCompanyId());
            PageHelper.startPage(companyQuery.getPageNum(), companyQuery.getPageSize());
            return (Page<CapitalPageVo>) companyMapper.getCapital(companyQuery);
        } else {
            return null;
        }
    }

    @Override
    public CompanyCapitalVo getCapitalDetail(Integer id) {
        return companyMapper.getCapitalDetail(id);
    }

    @Override
    public List<AgencyListVo> getCapitalAgencyList(Integer id) {
        return companyMapper.getCapitalAgencyList(id);
    }

    @Override
    public ConfigureRatesVo getConfigureRates(Integer id) {
        ConfigureRatesVo configureRates = companyMapper.getConfigureRates(id);
        List<ProductCompanyTiered> productCompanyTiereds = productCompanyTieredMapper.selectList(new LambdaQueryWrapper<ProductCompanyTiered>().eq(ProductCompanyTiered::getCompanyId, id));
        configureRates.setProductCompanyTiereds(productCompanyTiereds);
        return configureRates;
    }

    @Override
    public CompanyVo getCompanyDetail(Integer id) {
        Company company = getById(id);
        if (ObjectUtil.isNotEmpty(company)) {
            String companyType = company.getCompanyType();
            return SysConstant.COMPANY_TYPE_ONE.equals(companyType) ?
                    BeanUtil.copyProperties(getCapitalDetail(id), CompanyVo.class) :
                    BeanUtil.copyProperties(getAgencyDetail(id), CompanyVo.class);
        }
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deductingBalanceMain(OutInfo outInfo, String incomingOrder, Integer incomingId, Integer debtId,
                                     String type, Integer companyId, String amount, String clientTransId) {

        Integer lockCompanyId = null;
        if (incomingId != null) {//非入金
            companyId = incomingInfoMapper.selectById(incomingId).getCompanyId();
        }

        Company company = companyMapper.selectById(companyId);
        if (!SysConstant.ACCOUNTING_TYPE_ONE.equals(company.getAccountingType())) {
            lockCompanyId = company.getBlocId();
        } else {
            lockCompanyId = companyId;
        }

        String lockName = SysConstant.FEE_LOCK + lockCompanyId;
        RLock lock = redissonClient.getLock(lockName);
        try {
            log.info("尝试获取锁: {}", lockName);
            lock.lock();
            log.info("成功获取锁: {}", lockName);
            //扣除服务费锁
            switch (type) {
                case SysConstant.BUSINESS_FEE_ONE:
                    deductingBalance(outInfo);
                    break;
                case SysConstant.BUSINESS_FEE_TWO:
                    deductingBalance1(debtId);
                    break;
                case SysConstant.BUSINESS_FEE_THREE:
                    deductingBalance2(outInfo, incomingOrder);
                    break;
                case SysConstant.BUSINESS_FEE_FOUR:
                    deductingBalance3(incomingId);
                    break;
                case SysConstant.BUSINESS_FEE_FIVE:
                    deductingBalance4(outInfo, incomingOrder);
                    break;
                case SysConstant.BUSINESS_FEE_SIX:
                    deductingBalance5(companyId, amount, clientTransId);
                    break;
                case SysConstant.BUSINESS_FEE_SEVEN:
                    deductingBalance6(incomingId);
                    break;
                case SysConstant.BUSINESS_FEE_EIGHT:
                    deductingBalance7(amount, companyId, clientTransId);
                    break;
            }
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("当前线程: {} 释放锁: {}", Thread.currentThread().getName(), lockName);
            }
        }

    }

    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("110");
        BigDecimal  cost = a.multiply(new BigDecimal(50)).divide(new BigDecimal(100000), 2, RoundingMode.HALF_UP);
            System.out.println(cost);
    }

    private void deductingBalance7(String amount, Integer companyId, String clientTransId) {
        BigDecimal bigDecimal1 = new BigDecimal(amount);
        BigDecimal cost;
        String rateConfig;
        String payType;
        Company company = companyMapper.selectById(companyId);
        //验证公司是否独立核算
        String accountingType = company.getAccountingType();
        Integer payCompanyId = companyId;
        if (!accountingType.equals(SysConstant.ACCOUNTING_TYPE_ONE)) {
            Integer blocId = company.getBlocId();
            company = companyMapper.selectById(blocId);
            payCompanyId = blocId;
        }
        if (company.getRepayAccountType().equals("1")) {
            BigDecimal repayAccountRate = company.getRepayAccountFee();
            payType = SysConstant.COST_REPAY_TYPE_ONE;
            //提现费率存的值,转换成‰ 除以1000;入金单位:分转换成元,除以100
            cost = bigDecimal1.multiply(repayAccountRate).divide(new BigDecimal(100000), 2, RoundingMode.HALF_UP);
            if (cost.compareTo(company.getRepayAccountFloor()) < 0) {
                cost = company.getRepayAccountFloor();
            }
            rateConfig = repayAccountRate + "‰";
        } else {
            payType = SysConstant.COST_REPAY_TYPE_TWO;
            cost = company.getRepayAccountFloor();
            rateConfig = cost + "元";
        }
        companyMapper.updateBalance(cost, payCompanyId);
        //新增消耗明细表
        ConsumeDetail consumeDetail = new ConsumeDetail();
        consumeDetail.setCompanyId(companyId);
        consumeDetail.setType(SysConstant.COST_TYPE_EIGHT);
        consumeDetail.setPayType(payType);
        consumeDetail.setCost(cost);
        consumeDetail.setRateConfig(rateConfig);
        consumeDetail.setTransactionType(SysConstant.TRANSACTION_TYPE_THREE);
        consumeDetail.setOrderNo(clientTransId);
        consumeDetailMapper.insert(consumeDetail);
    }


    /**
     * 扣除服务费 --产品
     *
     * @param outInfo
     */

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deductingBalance(OutInfo outInfo) {
        BigDecimal loanAmount = outInfo.getLoanAmount();
        Integer companyId = outInfo.getCompanyId();
        IncomingInfo incomingInfo = incomingInfoMapper.selectById(outInfo.getIncomingId());
        Integer productId = incomingInfo.getProductId();
        Company company = companyMapper.selectById(companyId);
        String accountingType = company.getAccountingType();
        ProductCompany productCompany;
        Integer payCompanyId = companyId;
        //验证公司是否独立核算
        if (accountingType.equals(SysConstant.ACCOUNTING_TYPE_ONE)) {
            LambdaQueryWrapper<ProductCompany> wrapper = new LambdaQueryWrapper<ProductCompany>().eq(ProductCompany::getProductId, productId).eq(ProductCompany::getCompanyId, companyId);
            productCompany = productCompanyMapper.selectOne(wrapper);
        } else {
            Integer blocId = company.getBlocId();
            LambdaQueryWrapper<ProductCompany> wrapper = new LambdaQueryWrapper<ProductCompany>().eq(ProductCompany::getProductId, productId).eq(ProductCompany::getCompanyId, blocId);
            productCompany = productCompanyMapper.selectOne(wrapper);
            payCompanyId = blocId;
        }
        BigDecimal cost = null;
        String rateConfig = "";
        Integer chargeType = productCompany.getChargeType();
        if (chargeType == 2) {
            //固定金额收费
            cost = productCompany.getChargeAmount();
            rateConfig = cost + "元";
        } else if (chargeType == 1) {
            //百分比收费
            BigDecimal chargeProportion = productCompany.getChargeProportion();
            cost = loanAmount.multiply(chargeProportion).divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
            rateConfig = chargeProportion + "‰";
        } else {
            //阶梯收费
            List<ProductCompanyTiered> tiers = productCompanyTieredMapper.selectList(new LambdaQueryWrapper<ProductCompanyTiered>()
                    .eq(ProductCompanyTiered::getProductId, productId).eq(ProductCompanyTiered::getCompanyId, payCompanyId).orderByAsc(ProductCompanyTiered::getId));
            for (ProductCompanyTiered tier : tiers) {
                BigDecimal min = tier.getChargeAmountMin();
                BigDecimal max = tier.getChargeAmountMax();

                // 修正区间判断：第一个区间包含min，后续区间不包含min
                boolean isFirstTier = tiers.indexOf(tier) == 0;
                boolean inRange = isFirstTier
                        ? loanAmount.compareTo(min) >= 0 && loanAmount.compareTo(max) <= 0  // 第一个区间：[min, max]
                        : loanAmount.compareTo(min) > 0 && loanAmount.compareTo(max) <= 0;   // 后续区间：(min, max]

                if (inRange) {
                    BigDecimal proportion = tier.getChargeProportion();
                    cost = loanAmount.multiply(proportion)
                            .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
                    rateConfig = proportion + "‰";
                    break;
                }
            }
        }
        if (cost == null) {
            cost = new BigDecimal(0);
        }
        companyMapper.updateBalance(cost, payCompanyId);

        //新增消耗明细表
        ConsumeDetail consumeDetail = new ConsumeDetail();
        consumeDetail.setCompanyId(companyId);
        consumeDetail.setOrderNo(incomingInfo.getIncomingOrder());
        consumeDetail.setType(SysConstant.COST_TYPE_ONE);
        consumeDetail.setPayType(chargeType + "");
        consumeDetail.setAmount(loanAmount);
        consumeDetail.setCost(cost);
        consumeDetail.setRateConfig(rateConfig);
        consumeDetail.setTransactionType(SysConstant.TRANSACTION_TYPE_ZERO);
        consumeDetailMapper.insert(consumeDetail);
    }

    /**
     * 扣除服务费 --公证书执行书
     *
     * @param debtId （债权id）
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deductingBalance1(Integer debtId) {
        //扣除公证书执行书服务费
        Debt debt = debtMapper.selectById(debtId);
        Integer companyId = debt.getCompanyId();
        IncomingInfo info = incomingInfoMapper.selectById(debt.getIncomingId());
        Company company = companyMapper.selectById(companyId);
        String accountingType = company.getAccountingType();
        Integer payCompanyId = companyId;
        //验证公司是否独立核算
        if (!accountingType.equals(SysConstant.ACCOUNTING_TYPE_ONE)) {
            Integer blocId = company.getBlocId();
            company = companyMapper.selectById(blocId);
            payCompanyId = blocId;
        }
        String executeChargeType = company.getExecuteChargeType();
        BigDecimal cost;
        String rateConfig;
        BigDecimal remainingShouldRepayPrincipal = debt.getRemainingShouldRepayPrincipal();
        BigDecimal remainingShouldRepayInterest = debt.getRemainingShouldRepayInterest();
        BigDecimal amount = remainingShouldRepayPrincipal.add(remainingShouldRepayInterest);
        if (SysConstant.COST_REPAY_TYPE_ONE.equals(executeChargeType)) {
            BigDecimal executeChargeRate = company.getExecuteChargeRate();
            cost = amount.multiply(executeChargeRate.divide(new BigDecimal(100), 5, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP);
            rateConfig = executeChargeRate + "%";
            if (cost.compareTo(company.getExecuteChargeFloor()) < 0) {
                cost = company.getExecuteChargeFloor();
            }
        } else {
            cost = company.getExecuteChargeFloor();
            rateConfig = cost + "元";
        }
        companyMapper.updateBalance(cost, payCompanyId);
        //新增消耗明细表
        ConsumeDetail consumeDetail = new ConsumeDetail();
        consumeDetail.setCompanyId(companyId);
        consumeDetail.setType(SysConstant.COST_TYPE_FIVE);
        consumeDetail.setPayType(executeChargeType);
        consumeDetail.setAmount(amount);
        consumeDetail.setCost(cost);
        consumeDetail.setOrderNo(info.getIncomingOrder());
        consumeDetail.setRateConfig(rateConfig);
        consumeDetail.setTransactionType(SysConstant.TRANSACTION_TYPE_ZERO);
        consumeDetailMapper.insert(consumeDetail);
    }



    /**
     * 扣除服务费 --公证书
     *
     * @param outInfo
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deductingBalance2(OutInfo outInfo, String incomingOrder) {
        //扣除公证书服务费
        Integer companyId = outInfo.getCompanyId();
        Company company = companyMapper.selectById(companyId);
        String executeChargeType = company.getNotarizationChargeType();
        BigDecimal cost;
        String rateConfig;
        BigDecimal outAmount = outInfo.getOutLoan();
        //验证公司是否独立核算
        String accountingType = company.getAccountingType();
        Integer payCompanyId = companyId;
        if (!accountingType.equals(SysConstant.ACCOUNTING_TYPE_ONE)) {
            Integer blocId = company.getBlocId();
            company = companyMapper.selectById(blocId);
            payCompanyId = blocId;
        }
        if (SysConstant.COST_REPAY_TYPE_ONE.equals(executeChargeType)) {
            BigDecimal notarizationChargeRate = company.getNotarizationChargeRate();
            cost = outAmount.multiply(notarizationChargeRate.divide(new BigDecimal(100), 5, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP);
            if (cost.compareTo(company.getNotarizationChargeFloor()) < 0) {
                cost = company.getNotarizationChargeFloor();
            }
            rateConfig = notarizationChargeRate + "%";
        } else {
            cost = company.getNotarizationChargeFloor();
            rateConfig = cost + "元";
        }
        companyMapper.updateBalance(cost, payCompanyId);
        //新增消耗明细表
        ConsumeDetail consumeDetail = new ConsumeDetail();
        consumeDetail.setCompanyId(companyId);
        consumeDetail.setType(SysConstant.COST_TYPE_FOUR);
        consumeDetail.setPayType(executeChargeType);
        consumeDetail.setAmount(outAmount);
        consumeDetail.setCost(cost);
        consumeDetail.setOrderNo(incomingOrder);
        consumeDetail.setRateConfig(rateConfig);
        consumeDetail.setTransactionType(SysConstant.TRANSACTION_TYPE_ZERO);
        consumeDetailMapper.insert(consumeDetail);
    }

    /**
     * 扣除合同单笔服务费
     *
     * @param incomingId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deductingBalance3(Integer incomingId) {
        IncomingInfo incomingInfo = incomingInfoMapper.selectById(incomingId);
        Integer companyId = incomingInfo.getCompanyId();
        Company company = companyMapper.selectById(companyId);
        //验证公司是否独立核算
        String accountingType = company.getAccountingType();
        Integer payCompanyId = companyId;
        if (!accountingType.equals(SysConstant.ACCOUNTING_TYPE_ONE)) {
            Integer blocId = company.getBlocId();
            company = companyMapper.selectById(blocId);
            payCompanyId = blocId;
        }
        if (company.getContractChargeType().equals("2")) {
            return;
        }
        companyMapper.updateBalance(company.getContractFee(), payCompanyId);
        //新增消耗明细表
        ConsumeDetail consumeDetail = new ConsumeDetail();
        consumeDetail.setCompanyId(companyId);
        consumeDetail.setType(SysConstant.COST_TYPE_SIX);
        consumeDetail.setPayType(SysConstant.COST_REPAY_TYPE_TWO);
        consumeDetail.setCost(company.getContractFee());
        consumeDetail.setRateConfig(company.getContractFee() + "元");
        consumeDetail.setOrderNo(incomingInfo.getIncomingOrder());
        consumeDetail.setTransactionType(SysConstant.TRANSACTION_TYPE_ZERO);
        consumeDetailMapper.insert(consumeDetail);
    }

    /**
     * 扣除放款服务费
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deductingBalance4(OutInfo outInfo, String incomingOrder) {
        Integer companyId = outInfo.getCompanyId();
        Company company = companyMapper.selectById(companyId);
        //验证公司是否独立核算
        String accountingType = company.getAccountingType();
        Integer payCompanyId = companyId;
        if (!accountingType.equals(SysConstant.ACCOUNTING_TYPE_ONE)) {
            Integer blocId = company.getBlocId();
            company = companyMapper.selectById(blocId);
            payCompanyId = blocId;
        }
        BigDecimal cost = company.getOutServiceFee();
        companyMapper.updateBalance(cost, payCompanyId);
        //新增消耗明细表
        ConsumeDetail consumeDetail = new ConsumeDetail();
        consumeDetail.setCompanyId(companyId);
        consumeDetail.setType(SysConstant.COST_TYPE_TWO);
        consumeDetail.setPayType(SysConstant.COST_REPAY_TYPE_TWO);
        consumeDetail.setAmount(outInfo.getLoanAmount());
        consumeDetail.setCost(cost);
        consumeDetail.setRateConfig(cost + "元");
        consumeDetail.setTransactionType(SysConstant.TRANSACTION_TYPE_ZERO);
        consumeDetail.setOrderNo(incomingOrder);
        consumeDetailMapper.insert(consumeDetail);
    }

    /**
     * 收取入金服务费
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deductingBalance5(Integer companyId, String amount, String client_trans_id) {
        BigDecimal bigDecimal1 = new BigDecimal(amount);
        BigDecimal cost;
        String rateConfig;
        String payType;
        Company company = companyMapper.selectById(companyId);
        //验证公司是否独立核算
        String accountingType = company.getAccountingType();
        Integer payCompanyId = companyId;
        if (!accountingType.equals(SysConstant.ACCOUNTING_TYPE_ONE)) {
            Integer blocId = company.getBlocId();
            company = companyMapper.selectById(blocId);
            payCompanyId = blocId;
        }
        if (company.getDepositType().equals("1")) {
            BigDecimal depositRate = company.getDepositRate();
            payType = SysConstant.COST_REPAY_TYPE_ONE;
            //入金费率存的值,转换成‰ 除以1000;入金单位:分转换成元,除以100
            BigDecimal divide = depositRate.divide(new BigDecimal(100000), 2, RoundingMode.HALF_UP);
            cost = bigDecimal1.multiply(divide);
            rateConfig = depositRate + "‰";
        } else {
            payType = SysConstant.COST_REPAY_TYPE_TWO;
            cost = company.getDepositAmount();
            rateConfig = cost + "元";
        }
        companyMapper.updateBalance(cost, payCompanyId);
        //新增消耗明细表
        ConsumeDetail consumeDetail = new ConsumeDetail();
        consumeDetail.setCompanyId(companyId);
        consumeDetail.setType(SysConstant.COST_TYPE_THREE);
        consumeDetail.setPayType(payType);
        consumeDetail.setCost(cost);
        consumeDetail.setRateConfig(rateConfig);
        consumeDetail.setTransactionType(SysConstant.TRANSACTION_TYPE_TWO);
        consumeDetail.setOrderNo(client_trans_id);
        consumeDetailMapper.insert(consumeDetail);
    }

    /**
     * 扣除合同服务费（打包收费）
     *
     * @param incomingId
     */
    @Transactional(rollbackFor = Exception.class)
    public void deductingBalance6(Integer incomingId) {
        IncomingInfo incomingInfo = incomingInfoMapper.selectById(incomingId);
        Integer companyId = incomingInfo.getCompanyId();
        Company company = companyMapper.selectById(companyId);
        //验证公司是否独立核算
        String accountingType = company.getAccountingType();
        Integer payCompanyId = companyId;
        if (!accountingType.equals(SysConstant.ACCOUNTING_TYPE_ONE)) {
            Integer blocId = company.getBlocId();
            company = companyMapper.selectById(blocId);
            payCompanyId = blocId;
        }
        if (company.getContractChargeType().equals("1")) {
            return;
        }
        BigDecimal contractFeeTotal = company.getContractFeeTotal();
        companyMapper.updateBalance(contractFeeTotal, payCompanyId);
        //新增消耗明细表
        ConsumeDetail consumeDetail = new ConsumeDetail();
        consumeDetail.setCompanyId(companyId);
        consumeDetail.setType(SysConstant.COST_TYPE_SIX);
        consumeDetail.setPayType(SysConstant.COST_REPAY_TYPE_TWO);
        consumeDetail.setCost(contractFeeTotal);
        consumeDetail.setRateConfig(contractFeeTotal + "元");
        consumeDetail.setOrderNo(incomingInfo.getIncomingOrder());
        consumeDetail.setTransactionType(SysConstant.TRANSACTION_TYPE_ZERO);
        consumeDetailMapper.insert(consumeDetail);
    }


    @Override
    public AgencyPreview getAgencyPreview() {
        //绑定代理公司数(进件中)
        Integer companyId = SecurityUtil.getLoginCompanyId();
        LambdaQueryWrapper<Company> wrapper = new LambdaQueryWrapper<Company>()
                .eq(Company::getCapitalId, companyId)
                .eq(Company::getCompanyType, SysConstant.USER_COMPANY_TYPE_THREE)
                .eq(Company::getIncomingStatus, SysConstant.INCOMING_STATUS_ENABLE);
        Integer agencyCounts = companyMapper.selectCount(wrapper);
        //代理公司总员工数
        List<Integer> agencyIds = companyMapper.selectAgencyCount(companyId);

        Integer agencyUserCounts = 0;
        Integer outCounts = 0;
        if (CollectionUtil.isNotEmpty(agencyIds)) {
            agencyUserCounts = sysUserMapper.selectCount(new LambdaQueryWrapper<SysUser>().in(SysUser::getCompanyId, agencyIds));

            outCounts = outInfoMapper.selectOutCounts(agencyIds);
        }
        AgencyPreview agencyPreview = new AgencyPreview();
        agencyPreview.setAgencyCounts(agencyCounts);
        agencyPreview.setOutCounts(outCounts);
        agencyPreview.setAgencyUserCounts(agencyUserCounts);
        return agencyPreview;
    }

    @Override
    public CompanyCapital getCapitalDetails(Integer id) {
        CompanyCapitalVo capitalDetail = companyMapper.getCapitalDetail(id);
        ConfigureRatesVo configureRates = companyMapper.getConfigureRates(id);
        CompanyCapital companyCapital = BeanUtil.copyProperties(capitalDetail, CompanyCapital.class);
        companyCapital.setConfigureRatesVo(configureRates);
        return companyCapital;

    }

    @Override
    public void updateIncomingStatus(UpdateIncomingStatus updateIncomingStatus) {
        Integer companyId = updateIncomingStatus.getCompanyId();
        Company company = companyMapper.selectById(companyId);
        //如果代理,检查资方开关是否开启
        if (company.getCompanyType().equals(SysConstant.COMPANY_TYPE_TOW)) {
            Integer capitalId = company.getCapitalId();
            Company capital = companyMapper.selectById(capitalId);
            String incomingStatus = capital.getIncomingStatus();
            if (incomingStatus.equals(SysConstant.INCOMING_STATUS_DISABLE)) {
                throw new XkdException("该代理公司的资方进件状态已禁用");
            }
        }
        Integer count = companyContractMapper.selectCount(new LambdaQueryWrapper<CompanyContract>()
                .eq(CompanyContract::getCompanyId, companyId).eq(CompanyContract::getStatus, SysConstant.CONTRACT_TODO));
        if (count > 0) {
            throw new XkdException("公司合同未签署完成");
        }
        companyMapper.updateIncomingStatus(updateIncomingStatus);
    }

    /**
     * @description: 获取资方id和资方名称
     * @author: ZCH
     * @date: 2025/3/31 0031 11:15
     * @param: []
     * @return: java.util.List<com.xd.core.company.vo.CompanyInfoVo>
     **/
    @Override
    public List<CompanyInfoVo> getCapitals() {
        Company company = SecurityUtil.getLoginUser().getCompany();
        String companyType = company.getCompanyType();
        if (SysConstant.COMPANY_TYPE_THREE.equals(companyType)) {
            return companyMapper.getBlocCapital(company.getId());
        } else {
            return companyMapper.getCapitals();
        }
    }

    @Override
    public List<CompanyInfoVo> getAllCompany() {
        return companyMapper.getAllCompany();
    }

    @Override
    public List<CompanyInfoVo> getAgents(Integer companyId) {
        return companyMapper.getAgents(companyId);
    }

    @Override
    public CompanyDetailVo getCapitalDetailPublic(Integer companyId) {
        return companyMapper.getCapitalDetailPublic(companyId);
    }

    @Override
    public List<CompanyVo1> getCapitalsFinance() {
        Company company = SecurityUtil.getLoginUser().getCompany();
        String companyType = company.getCompanyType();
        if (SysConstant.COMPANY_TYPE_THREE.equals(companyType)) {
            return companyMapper.getCapitalsFinance(company.getId());
        } else {
            return companyMapper.getCapitalsFinance1();
        }
    }

    @Override
    public CompanyAgencyVo getPassAgencyList(Integer companyId) {
        return companyMapper.getPassAgencyList(companyId);
    }

    @Override
    public void exportCapitalList(CompanyQuery companyQuery, Integer id) {
        String name = "资方列表excel文件" + UUID.randomUUID().toString().replace("-", "");
        Integer companyId = SecurityUtil.getLoginCompanyId();
        FileOutputStream fileOutputStream = null;
        MissionCenterInfo missionCenterInfo = new MissionCenterInfo();
        missionCenterInfo.setId(id);
        missionCenterInfo.setFileName(name + ".xlsx");

        String filePath = localPathDir + exportFile + "/" + companyId;
        File dirFile = new File(filePath);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }

        try {
            List<RowHeightColWidthModel> rowHeightColWidthList = new ArrayList<>();
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 0, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 1, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 2, 10));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 3, 15));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 4, 10));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 5, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 6, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 7, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 8, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 9, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 10, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 11, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 12, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 13, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 14, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 15, 20));
            File file = new File(filePath + "/" + name + ".xlsx");
            fileOutputStream = new FileOutputStream(file);

            ExcelWriter write = EasyExcel.write(fileOutputStream, IncomingInfoPageVo.class).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(name).registerWriteHandler(new CustomRowHeightColWidthHandler(rowHeightColWidthList)).build();
//            query.setPageSize(0);
            List<CapitalPageVo> list = getCapitalList(companyQuery);
            write.write(list, writeSheet);
            write.finish();
            fileOutputStream.flush();
            //修改文件状态 导出成功
            missionCenterInfo.setFileStatus(SysConstant.YSZT_FILE_STATUS_TOW);
            missionCenterInfo.setFileUrl(exportFile + "/" + companyId + "/" + name + ".xlsx");
            missionCenterInfoMapper.updateById(missionCenterInfo);
        } catch (Exception e) {
            //修改文件状态 导出失败
            missionCenterInfo.setFileStatus(SysConstant.YSZT_FILE_STATUS_THREE);
            missionCenterInfoMapper.updateById(missionCenterInfo);
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void exportAgencyList(CompanyQuery companyQuery, Integer id) {
        String name = "已通过代理列表excel文件" + UUID.randomUUID().toString().replace("-", "");
        Integer companyId = SecurityUtil.getLoginCompanyId();
        FileOutputStream fileOutputStream = null;
        MissionCenterInfo missionCenterInfo = new MissionCenterInfo();
        missionCenterInfo.setId(id);
        missionCenterInfo.setFileName(name + ".xlsx");

        String filePath = localPathDir + exportFile + "/" + companyId;
        File dirFile = new File(filePath);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }

        try {
            List<RowHeightColWidthModel> rowHeightColWidthList = new ArrayList<>();
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 0, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 1, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 2, 10));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 3, 15));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 4, 10));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 5, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 6, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 7, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 8, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 9, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 10, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 11, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 12, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 13, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 14, 20));
            File file = new File(filePath + "/" + name + ".xlsx");
            fileOutputStream = new FileOutputStream(file);

            ExcelWriter write = EasyExcel.write(fileOutputStream, IncomingInfoPageVo.class).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(name).registerWriteHandler(new CustomRowHeightColWidthHandler(rowHeightColWidthList)).build();
//            query.setPageSize(0);
            List<CompanyPageVo> list = getAgencyList1(companyQuery);
            write.write(list, writeSheet);
            write.finish();
            fileOutputStream.flush();
            //修改文件状态 导出成功
            missionCenterInfo.setFileStatus(SysConstant.YSZT_FILE_STATUS_TOW);
            missionCenterInfo.setFileUrl(exportFile + "/" + companyId + "/" + name + ".xlsx");
            missionCenterInfoMapper.updateById(missionCenterInfo);
        } catch (Exception e) {
            //修改文件状态 导出失败
            missionCenterInfo.setFileStatus(SysConstant.YSZT_FILE_STATUS_THREE);
            missionCenterInfoMapper.updateById(missionCenterInfo);
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void exportUnCheckAgencyList(CompanyQuery companyQuery, Integer id) {
        String name = "未通过代理列表excel文件" + UUID.randomUUID().toString().replace("-", "");
        Integer companyId = SecurityUtil.getLoginCompanyId();
        FileOutputStream fileOutputStream = null;
        MissionCenterInfo missionCenterInfo = new MissionCenterInfo();
        missionCenterInfo.setId(id);
        missionCenterInfo.setFileName(name + ".xlsx");

        String filePath = localPathDir + exportFile + "/" + companyId;
        File dirFile = new File(filePath);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }

        try {
            List<RowHeightColWidthModel> rowHeightColWidthList = new ArrayList<>();
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 0, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 1, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 2, 10));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 3, 15));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 4, 10));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 5, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 6, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 7, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 8, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 9, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 10, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 11, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 12, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 13, 20));
            rowHeightColWidthList.add(RowHeightColWidthModel.createColWidthModel(name, 14, 20));
            File file = new File(filePath + "/" + name + ".xlsx");
            fileOutputStream = new FileOutputStream(file);

            ExcelWriter write = EasyExcel.write(fileOutputStream, IncomingInfoPageVo.class).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(name).registerWriteHandler(new CustomRowHeightColWidthHandler(rowHeightColWidthList)).build();
//            query.setPageSize(0);
            List<CompanyPageVo> list = getAgencyList(companyQuery);
            write.write(list, writeSheet);
            write.finish();
            fileOutputStream.flush();
            //修改文件状态 导出成功
            missionCenterInfo.setFileStatus(SysConstant.YSZT_FILE_STATUS_TOW);
            missionCenterInfo.setFileUrl(exportFile + "/" + companyId + "/" + name + ".xlsx");
            missionCenterInfoMapper.updateById(missionCenterInfo);
        } catch (Exception e) {
            //修改文件状态 导出失败
            missionCenterInfo.setFileStatus(SysConstant.YSZT_FILE_STATUS_THREE);
            missionCenterInfoMapper.updateById(missionCenterInfo);
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /***
     * @description 修改代扣开关状态
     * @author Zch
     * @date 16:46 2025/6/3 星期二
     * @param updateWithholdSwitchStatus
     * @return void
     **/

    @Override
    public void updateWithholdSwitchStatus(UpdateWithholdSwitchStatus updateWithholdSwitchStatus) {
        XkdUtil.checkNonNullProperties(updateWithholdSwitchStatus, "companyId", "withholdSwitch");
        companyMapper.updateWithholdSwitchStatus(updateWithholdSwitchStatus.getCompanyId(), updateWithholdSwitchStatus.getWithholdSwitch());
    }

    @Override
    public void addBloc(AddCapitalUserDto addCapitalUserDto) {
        if (!checkPhoneRepetition(addCapitalUserDto.getPhone()))
            throw new XkdException("用户手机号已注册");
        if (!checkUnifiedSocialCreditCode(addCapitalUserDto.getUnifiedSocialCreditCode()))
            throw new XkdException("统一社会信用代码已注册");
        /*
         * 插入公司
         * */
        Company company = new Company();
        BeanUtil.copyProperties(addCapitalUserDto, company);
        company.setCompanyType(SysConstant.COMPANY_TYPE_THREE);
        companyMapper.insert(company);
        /*
         * 插入用户
         * */
        SysUser sysUser = new SysUser();
        sysUser.setPhone(addCapitalUserDto.getPhone());
        sysUser.setUserName(addCapitalUserDto.getCompanyName());
        //校验密码正则规则
        String decrypt = RSAUtils.privateDecrypt(addCapitalUserDto.getPassword(), passWordKeyProperties.getPrivateKey());
        String rex = "^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{8,16}$";
        if (!Pattern.matches(rex, decrypt)) {
            throw new XkdException("密码不符合规则");
        }
        sysUser.setPassword(bCryptPasswordEncoder.encode(decrypt));
        sysUser.setCompanyId(company.getId());
        sysUser.setCompanyType(SysConstant.USER_COMPANY_TYPE_FOUR);
        sysUser.setUserType(SysConstant.USER_TYPE_P);
        sysUser.setCreateBy(SecurityUtil.getLoginUserId());
        sysUser.setDataPertType(SysConstant.DATA_PERT_TYPE_FOUR);
        sysUserMapper.insert(sysUser);
        /*
         * 绑定角色
         * */
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setCompanyId(company.getId())
                .setUserId(sysUser.getId())
                .setRoleId(SysConstant.SYS_ROLE_BLOC_SUPER);
        sysUserRoleMapper.insert(sysUserRole);
        /*
         * 新建公司部门
         * */
        GroupInfo groupInfo = new GroupInfo();
        groupInfo.setCompanyId(company.getId())
                .setPid(SysConstant.PID_PARENT)
                .setGroupName(company.getCompanyName() + "总部");
        groupInfoMapper.insert(groupInfo);

        UserGroup userGroup = new UserGroup();
        userGroup.setCompanyId(company.getId())
                .setUserId(sysUser.getId())
                .setGroupId(groupInfo.getId());
        userGroupMapper.insert(userGroup);
        /*
         * 产品服务费率配置
         * */
        List<ProductCompany> productCompanies = addCapitalUserDto.getProductCompanies();
        productCompanies.forEach(p -> {
            p.setCompanyId(company.getId());
        });
        productCompanyMapper.insertBatch(productCompanies);

        List<ProductCompanyTiered> productCompanyTiereds = addCapitalUserDto.getProductCompanyTiereds();
        // 提取产品ID列表并查询产品信息
        List<Integer> productIds = productCompanyTiereds.stream()
                .map(ProductCompanyTiered::getProductId)
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(productIds)) {
            Map<Integer, Product> productMap = productMapper.selectList(
                            new LambdaQueryWrapper<Product>().in(Product::getProductId, productIds)
                    ).stream()
                    .collect(Collectors.toMap(Product::getProductId, Function.identity()));

            // 验证每个阶梯收费设置
            for (ProductCompanyTiered tiered : productCompanyTiereds) {
                Product product = productMap.get(tiered.getProductId());
                if (product == null) {
                    throw new XkdException("关联的产品不存在: " + tiered.getProductId());
                }

                // 验证阶梯金额是否在产品允许范围内
                if (tiered.getChargeAmountMin().compareTo(product.getMinAmount()) < 0 ||
                        tiered.getChargeAmountMax().compareTo(product.getMaxAmount()) > 0) {
                    throw new XkdException("阶梯收费金额超出产品金额限制");
                }

                tiered.setCompanyId(company.getId());
            }

            // 批量插入阶梯收费设置
            productCompanyTieredMapper.insertBatch(productCompanyTiereds);

        }
        // 按产品分组并验证阶梯连续性
        Map<Integer, List<ProductCompanyTiered>> productTierMap = productCompanyTiereds.stream()
                .collect(Collectors.groupingBy(ProductCompanyTiered::getProductId));

        for (List<ProductCompanyTiered> tierList : productTierMap.values()) {
            // 按ID排序确保顺序
            tierList.sort(Comparator.comparingInt(ProductCompanyTiered::getId));

            // 验证阶梯连续性
            for (int i = 1; i < tierList.size(); i++) {
                if (tierList.get(i).getChargeAmountMin().compareTo(tierList.get(i - 1).getChargeAmountMax()) != 0) {
                    throw new XkdException("阶梯收费设置不连续，最小值必须等于上一级最大值");
                }
            }
        }
        /*
         * 插入电子账号
         * */
        CompanyAccount companyAccount = new CompanyAccount();
        companyAccount.setCompanyId(company.getId());
        companyAccountMapper.insert(companyAccount);
    }

    @Override
    public void updateBloc(AddCapitalUserDto addCapitalUserDto) {
        if (!checkPhoneRepetition(addCapitalUserDto.getPhone()))
            throw new XkdException("用户手机号已注册");
        if (!checkUnifiedSocialCreditCode(addCapitalUserDto.getUnifiedSocialCreditCode()))
            throw new XkdException("统一社会信用代码已注册");
        /*
         * 修改公司
         * */
        Company company = new Company();
        BeanUtil.copyProperties(addCapitalUserDto, company);
        companyMapper.updateById(company);
        Integer companyId = addCapitalUserDto.getId();
        /*
         * 修改用户
         * */
        SysUser sysUser = new SysUser();
        sysUser.setPhone(addCapitalUserDto.getPhone());
        sysUser.setUserName(addCapitalUserDto.getCompanyName());
        //修改集团下所有资方名称
        companyMapper.updateCapaitalBlocName(companyId, addCapitalUserDto.getBlocName());
        //校验密码正则规则
        if (StringUtils.isNotEmpty(addCapitalUserDto.getPassword())) {
            String decrypt = RSAUtils.privateDecrypt(addCapitalUserDto.getPassword(), passWordKeyProperties.getPrivateKey());
            String rex = "^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{8,16}$";
            if (!Pattern.matches(rex, decrypt)) {
                throw new XkdException("密码不符合规则");
            }
            Integer id = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                    .eq(SysUser::getCompanyId, companyId)
                    .eq(SysUser::getUserType, SysConstant.USER_TYPE_P)).getId();
            redisTemplate.delete(redisLogin + id);
            redisTemplate.delete(redisToken + id);
            sysUser.setPassword(bCryptPasswordEncoder.encode(decrypt));
        }
        sysUserMapper.update(sysUser, new LambdaQueryWrapper<SysUser>().eq(SysUser::getCompanyId, company.getId()).eq(SysUser::getUserType, SysConstant.USER_TYPE_P));
        /*
         * 产品服务费率配置修改
         * */
        List<ProductCompany> productCompanies = addCapitalUserDto.getProductCompanies();
        productCompanyMapper.delete(new LambdaQueryWrapper<ProductCompany>().eq(ProductCompany::getCompanyId, companyId));
        if (CollectionUtil.isNotEmpty(productCompanies)) {
            productCompanyMapper.insertBatch(productCompanies);
        }
        productCompanyTieredMapper.delete(new LambdaQueryWrapper<ProductCompanyTiered>().eq(ProductCompanyTiered::getCompanyId, companyId));
        List<ProductCompanyTiered> productCompanyTiereds = addCapitalUserDto.getProductCompanyTiereds();
        // 提取产品ID列表并查询产品信息
        List<Integer> productIds = productCompanyTiereds.stream()
                .map(ProductCompanyTiered::getProductId)
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(productIds)) {
            // 查询产品信息并转换为Map(产品ID -> 产品
            Map<Integer, Product> productMap = productMapper.selectList(
                            new LambdaQueryWrapper<Product>().in(Product::getProductId, productIds)
                    ).stream()
                    .collect(Collectors.toMap(Product::getProductId, Function.identity()));

            // 验证每个阶梯收费设置
            for (ProductCompanyTiered tiered : productCompanyTiereds) {
                Product product = productMap.get(tiered.getProductId());
                if (product == null) {
                    throw new XkdException("关联的产品不存在: " + tiered.getProductId());
                }

                // 验证阶梯金额是否在产品允许范围内
                if (tiered.getChargeAmountMin().compareTo(product.getMinAmount()) < 0 ||
                        tiered.getChargeAmountMax().compareTo(product.getMaxAmount()) > 0) {
                    throw new XkdException("阶梯收费金额超出产品金额限制");
                }

                tiered.setCompanyId(company.getId());
            }

            // 批量插入阶梯收费设置
            productCompanyTieredMapper.insertBatch(productCompanyTiereds);
        }


        // 按产品分组并验证阶梯连续性
        Map<Integer, List<ProductCompanyTiered>> productTierMap = productCompanyTiereds.stream()
                .collect(Collectors.groupingBy(ProductCompanyTiered::getProductId));

        for (List<ProductCompanyTiered> tierList : productTierMap.values()) {
            // 按ID排序确保顺序
            tierList.sort(Comparator.comparingInt(ProductCompanyTiered::getId));

            // 验证阶梯连续性
            for (int i = 1; i < tierList.size(); i++) {
                if (tierList.get(i).getChargeAmountMin().compareTo(tierList.get(i - 1).getChargeAmountMax()) != 0) {
                    throw new XkdException("阶梯收费设置不连续，最小值必须等于上一级最大值");
                }
            }
        }
    }

    @Override
    public Page<BlocPageVo> getBlocList(BlocQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        return companyMapper.getBlocList(query);
    }

    @Override
    public CompanyBloc getBloc(Integer id) {
        CompanyBloc blocDetail = companyMapper.getBloc(id);
        ConfigureRatesVo configureRates = companyMapper.getConfigureRates(id);
        blocDetail.setConfigureRatesVo(configureRates);
        return blocDetail;
    }

    @Override
    public List<CompanyCapitals> getBlocCapitals(Integer id) {
        return companyMapper.getBlocCapitals(id);
    }

    @Override
    public List<CompanyInfoVo> getInsuranceCompanys() {
        Company company = SecurityUtil.getLoginUser().getCompany();
        String companyType = company.getCompanyType();
        if (SysConstant.COMPANY_TYPE_THREE.equals(companyType)) {
            return companyMapper.getInsuranceBlocCapital(company.getId());
        } else {
            List<CompanyInfoVo> insuranceCapitals = companyMapper.getInsuranceCapitals();
            List<CompanyInfoVo> insuranceCompanys = companyMapper.getInsuranceCompanys();
            insuranceCompanys.addAll(insuranceCapitals);
            return insuranceCompanys.stream().distinct().collect(Collectors.toList());
        }
    }

    @Override
    public void freezeAccount(FreezeAccountDto freezeAccountDto) {
        companyMapper.updateFreezeAccount(freezeAccountDto);
    }


    //检查统一社会信用代码重复
    private boolean checkUnifiedSocialCreditCode(String a) {
        if (!StringUtils.isNotBlank(a)) {
            return true;
        }
        LambdaQueryWrapper<Company> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Company::getUnifiedSocialCreditCode, a);
        Integer integer = companyMapper.selectCount(lqw);
        //如果没有重复返回true
        return integer == 0;
    }
}
